
#include "NetStreamFilter.h"
#include "Dvdmedia.h"
const AMOVIESETUP_PIN sudOutputPinBitmap =
{
    L"Output",      // Obsolete, not used.
    FALSE,          // Is this pin rendered?
    TRUE,           // Is it an output pin?
    FALSE,          // Can the filter create zero instances?
    FALSE,          // Does the filter create multiple instances?
    &CLSID_NULL,    // Obsolete.
    NULL,           // Obsolete.
    1,              // Number of media types.
    NULL			// Pointer to media types.
};


CFactoryTemplate g_Templates[] =
{
    {
      g_wszNetStream,                // Name
      &CLSID_NetStreamFilter,        // CLSID
      CNetStream::CreateInstance,  // Method to create an instance of MyComponent
      NULL,                           // Initialization function
      NULL                           // Set-up information (for filters)
    }
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

STDAPI DllRegisterServer()
{
    return AMovieDllRegisterServer2( TRUE );
}

STDAPI DllUnregisterServer()
{
    return AMovieDllRegisterServer2( FALSE );
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule,DWORD  dwReason,LPVOID lpReserved)
{
	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}



//  COUTPUTPIN DEFINITIONS

COutputPin::COutputPin(IN TCHAR* szName,IN CBaseFilter* pFilter,IN CCritSec* pLock,OUT HRESULT* pHr,IN LPCWSTR pszName) : 
					CBaseOutputPin(szName,pFilter,pLock,pHr,pszName),
					CNetStreamFilterConfig(NAME("NetStream Pin"), CBasePin::GetOwner()),
					m_Callback(NULL)
{
	HRESULT hr;
	m_bTryMyTypesFirst=true;
}
HRESULT COutputPin::GetMediaType(int lPosition,CMediaType *pMediaType)
{
    CAutoLock cAutoLock(m_pLock);

	if(lPosition < 0) return E_INVALIDARG;
	if(lPosition > 0) return VFW_S_NO_MORE_ITEMS;

	*pMediaType = m_amt;
	m_Callback->GetMediaType(lPosition,pMediaType);
	return S_OK;
}
HRESULT COutputPin::CompleteConnect(IPin *pReceivePin)
{
    HRESULT hr;
    CheckPointer(pReceivePin, E_POINTER);
    CheckPointer(m_Callback, E_POINTER);
	//LockPin();
    if(FAILED(hr=__super::CompleteConnect(pReceivePin)))
		return hr;
	PIN_INFO* pinfo=new PIN_INFO();
	pReceivePin->QueryPinInfo(pinfo);
	FILTER_INFO* finfo=new FILTER_INFO();
	pinfo->pFilter->QueryFilterInfo(finfo);
	CMediaType cmt = m_mt;
    m_Callback->OnMediaTypeChanged(hr,&cmt); // Ignore return
	pReceiver=pReceivePin;
	//UnlockPin();
    return hr;
}

HRESULT COutputPin::CheckMediaType(const CMediaType *pmt)
{
    HRESULT hr;
    CheckPointer(pmt, E_POINTER);
    CheckPointer(m_Callback, E_POINTER);
    //LockPin();
    hr=m_Callback->CheckMediaType(pmt);
	//UnlockPin();
    return hr;
}

HRESULT COutputPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)
{
    ASSERT(pAlloc);
    ASSERT(pRequest);

    HRESULT hr = NOERROR;
	hr=m_Callback->OnDecideBufferSize(pAlloc,pRequest);

	return hr;
}


STDMETHODIMP COutputPin::SetPinMediaType(const AM_MEDIA_TYPE *amt)
{
    HRESULT hr = S_OK;
   // LockPin();
    if (!IsConnected())
    {
        if (!IsEqualGUID(amt->majortype, GUID_NULL))
        {

            hr = m_amt.Set(*amt);
        }
        else
        {
            hr = MAKE_HRESULT(1, FACILITY_WIN32, ERROR_INVALID_PARAMETER);
        }
    }
    else
    {
        hr = MAKE_HRESULT(1, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED);
    }
	//UnlockPin();
    return hr;
}

HRESULT COutputPin::Active()
{
	HRESULT hr=S_OK;
	CMediaType mt=m_amt;
	hr=__super::Active();
	hr=m_pAllocator->Commit();
	return hr;
}

HRESULT COutputPin::Inactive()
{
	HRESULT hr=S_OK;
	hr=__super::Inactive();
	hr=m_pAllocator->Decommit();
	return hr;
}

STDMETHODIMP COutputPin::DeliverPacket(const long StartTime,const long EndTime)
{
	HRESULT hr;
	LockPin();
	IMediaSample* pSample;
	hr=Active();
	hr=__super::GetDeliveryBuffer(&pSample,NULL,NULL,0);
	if(FAILED(hr))
		return hr;
	hr=m_Callback->OnDeliverSample(pSample);
	hr=__super::Deliver(pSample);
	hr=Inactive();
	pSample->Release();
	UnlockPin();
	return hr;
}
STDMETHODIMP COutputPin::SetPinAllocator()
{
	HRESULT hr;
	hr=m_Callback->OnSetPinAllocator(m_pAllocator);
	return hr;
}

STDMETHODIMP COutputPin::SetCallback(INetStreamFilterCB *pfn)
{
    HRESULT hr = S_OK;
    CheckPointer(pfn, E_POINTER);
    //LockPin();
    // Must set the media type first
    if (m_amt.IsValid())
    {
        m_Callback = pfn;
        m_Callback->AddRef();
    }
    else
    {
        hr = E_FAIL;
    }
	//UnlockPin();
    return hr;
}

STDMETHODIMP COutputPin::NonDelegatingQueryInterface(REFIID riid,void** ppv)
{
    HRESULT hr;

    // Try our local interface
    if (riid == IID_INetStreamFilterConfig)
    {
        hr = GetInterface((INetStreamFilterConfig*) this, ppv);
    }
    else
    {
        // Try the classes we derive from, first CSourceStream
		hr = CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);

    }

    return hr;
}


//  CNETSTREAM DEFINITIONS

CNetStream::CNetStream(IN TCHAR* tszName,IN LPUNKNOWN   punk,OUT HRESULT* phr) : 
				CBaseFilter(tszName,punk,&m_crtFilterLock,CLSID_NetStreamFilter),
				m_pVideoOutput(NULL),m_pAudioOutput(NULL)
{
    //  instantiate the output pin
    m_pVideoOutput=new COutputPin ( NAME ("CNetVideoOutputPin"),this,&m_crtFilterLock,phr,L"Video");
	m_pAudioOutput=new COutputPin ( NAME ("CNetAudioOutputPin"),this,&m_crtFilterLock,phr,L"Audio");
}

CBasePin* CNetStream::GetPin(int Index)
{
	CBasePin* pPin=NULL;
    //LockFilter();
    if(Index==0)
        pPin=m_pVideoOutput;
    else if(Index==1)
        pPin=m_pAudioOutput;
  //  UnlockFilter();
    return pPin;
}

CUnknown* CNetStream::CreateInstance(LPUNKNOWN punk,HRESULT* phr)
{
    CNetStream* pnf ;
    (*phr)=S_OK ;
    pnf=new CNetStream(NAME("CNetStreamFilter"),punk,phr);
    if (pnf == NULL || FAILED (* phr)) 
	{
        (*phr)=(FAILED(*phr) ? (*phr) : E_OUTOFMEMORY);
    }
    return pnf;
}



